package com.kaola.kaistory.mod.db;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class DbMgrImp implements DbMgr {
	public DbMgrImp(SQLiteDatabase db) {
		this.db = db;
	}

	DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

	@Override
	public void create(Class tableObj) {
		String sql = " CREATE TABLE IF NOT EXISTS " + getTableName(tableObj)
				+ "(";
		List<String> list = getCreateFields(tableObj);
		if (list == null || list.size() == 0)
			return;
		for (int i = 0; i < list.size(); i++) {
			sql += list.get(i);
			if (i != list.size() - 1) {
				sql += ",\n";
			}
		}
		sql += ");";
		create(sql);
	}

	@Override
	public void create(String sql) {
		db.execSQL(sql);
	}

	@Override
	public int update(Object data, List<String> sets, Map<String, String> wheres) {
		ContentValues values = new ContentValues();
		if (sets == null || sets.size() <= 0)
			return 0;
		for (String s : sets) {
			values.put(s, getValue(data, s));
			;
		}
		String whereClause = null;
		String[] whereArgs = null;
		Map<String, Object> where = getWhere(data, wheres);
		whereClause = (String) where.get(WHERE_CLAUSE);
		whereArgs = (String[]) where.get(WHERE_ARGS);
		db.update(getTableName(data.getClass()), values, whereClause, whereArgs);
		return 0;
	}

	private String getValue(Object obj, String fieldName) {
		String valStr = null;
		try {
			Field f = obj.getClass().getDeclaredField(fieldName);
			f.setAccessible(true);
			Object val = f.get(obj);
			if (val instanceof Date) {
				valStr = dateFormat.format(val);
			} else {
				valStr = val + "";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return valStr;
	}

	/**
	 * 这个接口在sqlite中无法返回执行状态
	 */
	@Override
	public int update(String sql) {
		db.execSQL(sql);
		return 0;
	}

	/**
	 * 此方法在sqlite中不支持
	 */
	@Override
	public ResultSet selectResultSet(Object data, Object obj,
			List<String> selects, Map<String, String> wheres) {
		return null;
	}

	/**
	 * 此方法在sqlite中不支持
	 * */
	@Override
	public <T> List<T> select(T data, Object obj, List<String> selects,
			Map<String, String> wheres) {
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> select(T data, List<String> selects,
			Map<String, String> wheres) {
		String[] columns = new String[] { "*" };
		if (selects != null && selects.size() > 0) {
			columns = selects.toArray(columns);
		}
		String whereClause = null;
		String[] whereArgs = null;
		Map<String,Object> where = getWhere(data, wheres);
		whereClause = (String)where.get(WHERE_CLAUSE);
		whereArgs = (String[])where.get(WHERE_ARGS);
		Cursor cursor = db.query(getTableName(data.getClass()), columns,
				whereClause, whereArgs, null, null, null);
		List<T> list = new ArrayList<T>();
		cursor.moveToFirst();
		while (cursor.moveToNext()) {
			T t = (T) getObj(data.getClass(), cursor);
			list.add(t);
		}
		return list;
	}

	/**
	 * 此方法在sqlite中不支持
	 */
	@Override
	public ResultSet select(String sql) {
		return null;
	}

	@Override
	public boolean insert(Object obj) {
		ContentValues values = new ContentValues();
		Field[] mFields = obj.getClass().getDeclaredFields();
		for (Field f : mFields) {
			String temp = getSpacialStartChar() + f.getName()
					+ getSpacialEndChar();
			values.put(temp, getValue(obj, f.getName()));
		}
		return db.insert(getTableName(obj.getClass()),
				getInsertColumes(obj.getClass()), values) != -1;
	}

	@Override
	public String getSpacialStartChar() {// sqlite中使用
		return "[";
	}

	@Override
	public String getSpacialEndChar() {// sqlite中使用
		return "]";
	}

	private SQLiteDatabase db = null;

	private String getTableName(Class obj) {
		return getSpacialStartChar() + obj.getSimpleName()
				+ getSpacialEndChar();
	}

	/**
	 * 带后面的","根据对象获取create数据库的语句
	 * */
	private List<String> getCreateFields(Class obj) {
		Class clazz = obj;
		List<String> fileds = new ArrayList<String>();
		Field[] mFields = clazz.getDeclaredFields();
		for (Field f : mFields) {
			f.setAccessible(true);
			Class type = f.getType();
			String temp = getSpacialStartChar() + f.getName()
					+ getSpacialEndChar();
			if (type == Boolean.class || type == boolean.class) {
				temp += " BOOL";
			} else if (type == Double.class || type == Float.class
					|| type == double.class || type == float.class) {
				temp += " REAL";
			} else if (type == int.class || type == Integer.class
					|| type == long.class || type == Long.class) {
				temp += " INTEGER";
			} else if (type == String.class || type == char.class
					|| java.util.Date.class.isAssignableFrom(type)) {
				temp += " TEXT";
			}
			fileds.add(temp);
		}
		return fileds;
	}

	private String getInsertColumes(Class clazz) {
		String sql = "";
		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			sql += fields[i].getName() + " ";
			if (i != fields.length - 1) {
				sql += ", ";
			}
		}
		return sql;
	}

	@Override
	public boolean delete(Object obj, Map<String, String> wheres) {
		String whereClause = null;
		String[] whereArgs = null;
		Map<String, Object> where = getWhere(obj, wheres);
		whereClause = (String) where.get(WHERE_CLAUSE);
		whereArgs = (String[]) where.get(WHERE_ARGS);
		Log.e("ajh", whereClause + "");
		return db.delete(getTableName(obj.getClass()), whereClause, whereArgs) > 0;
	}

	/**
	 * sqlite中午饭返回结果
	 * */
	@Override
	public boolean drop(Class obj) {
		db.execSQL("DROP TABLE " + getTableName(obj));
		return false;
	}

	private Map<String, Object> getWhere(Object data, Map<String, String> wheres) {
		String whereClause = null;
		String[] whereArgs = null;
		Map<String, Object> where = new HashMap<String, Object>();
		if (wheres != null && wheres.size() > 0) {
			whereClause = "";
			whereArgs = new String[wheres.size()];
			whereArgs = wheres.keySet().toArray(whereArgs);
			for (int i = 0; i < whereArgs.length; i++) {
				whereClause += wheres.get(whereArgs[i]);
				if (i != whereArgs.length - 1) {
					whereClause += " AND ";
				}
				Field f;
				try {
					f = data.getClass().getDeclaredField(whereArgs[i]);
					f.setAccessible(true);
					whereArgs[i] = f.get(data) + "";
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				}
			}
		}
		where.put(WHERE_CLAUSE, whereArgs);
		where.put(WHERE_ARGS, whereClause);
		return where;
	}

	public <T> T getObj(Class<T> clazz, Cursor cursor) {
		T t = null;
		try {
			t = (T) clazz.newInstance();
			for (String columnName : cursor.getColumnNames()) {
				Field field = t.getClass().getDeclaredField(columnName);// 去掉前后的标识
				field.setAccessible(true);
				Class type = field.getType();
				Log.d("ajh", "type:" + type);
				int index = cursor.getColumnIndex(columnName);
				Object val = null;
				if (type == Boolean.class || type == boolean.class) {
					val = cursor.getInt(index) > 0;
				} else if (type == Double.class || type == double.class) {
					val = cursor.getDouble(index);
				} else if (type == float.class || type == Float.class) {
					val = cursor.getFloat(index);
				} else if (type == int.class || type == Integer.class) {
					val = cursor.getInt(index);
				} else if (type == long.class || type == Long.class) {
					val = cursor.getLong(index);
				} else if (type == String.class) {
					val = cursor.getString(index);
				} else if (java.util.Date.class.isAssignableFrom(type)) {

					try {
						val = dateFormat.parse(cursor.getString(index));
						Constructor constructor = type.getDeclaredConstructor(long.class);
						constructor.setAccessible(true);
						val = constructor.newInstance(((java.util.Date) val)
								.getTime());
					} catch (Exception e) {
						e.printStackTrace();
						val = null;
					} 
				} else {// 不支类型
						// temp += " BLOB";
				}
				if (val != null) {
					field.set(t, val);
				}
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		return t;
	}

	private final static String WHERE_CLAUSE = "whereClause";
	private final static String WHERE_ARGS = "whereArgs";
}
